"""
增强版动作执行器
集成 Open Interpreter 风格的计算机控制功能
"""

import os
import time
from typing import Any, Dict, List, Optional, Tuple
from pathlib import Path

from .executor import ActionExecutor
from .open_interpreter_adapter import OpenInterpreterAdapter
from .computer_control import ComputerController
from .llm import DoubaoLLM
from .logger import log_event
from .tts import SpeechFeedback


class EnhancedActionExecutor(ActionExecutor):
    """
    增强版动作执行器
    在原有功能基础上，集成 Open Interpreter 风格的计算机控制能力
    """
    
    def __init__(self, llm: Optional[DoubaoLLM] = None):
        super().__init__(llm)
        self.oi_adapter = OpenInterpreterAdapter()
        self.computer_controller = ComputerController()
        # 记录最近一次成功打开的应用名，用于后续输入时聚焦窗口
        self.last_opened_app: Optional[str] = None

    def execute_actions(self, actions: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """
        执行动作列表，支持原有功能 + Open Interpreter 风格的计算机控制
        """
        results = []
        
        for action in actions:
            action_type = action.get("type", "")
            
            # 使用原有的执行逻辑处理已支持的动作类型
            if action_type in ["play_music", "write_article", "file_op", "web_search", "navigate", "browser_click"]:
                result = self._execute_legacy_action(action)
                results.append(result)
                
            # 使用增强的计算机控制功能处理新的动作类型
            elif action_type.startswith("computer_"):
                result = self._execute_computer_action(action)
                results.append(result)
                
            # 使用原有的应用控制，但增强错误处理
            elif action_type == "app_control":
                result = self._execute_enhanced_app_control(action)
                results.append(result)
                
            # 系统控制保持原有逻辑
            elif action_type == "system_control":
                result = self._execute_system_control(action)
                results.append(result)
                
            # 新增：支持微信消息发送（复用基础执行器逻辑）
            elif action_type == "wechat_message":
                contact = action.get("contact", "")
                text = action.get("text", "")
                ok, detail = self._execute_wechat_message(contact=contact, text=text)
                results.append({"action": "wechat_message", "success": ok, "detail": detail})
            else:
                result = self._execute_with_oi_adapter(action)
                results.append(result)
        
        return results

    def _execute_legacy_action(self, action: Dict[str, Any]) -> Dict[str, Any]:
        """执行原有的动作类型"""
        try:
            action_type = action.get("type", "")
            
            if action_type == "play_music":
                song_name = action.get("song_name", "")
                success, detail = self.play_music(song_name)
                return {"action": "play_music", "success": success, "detail": detail}
                
            elif action_type == "write_article":
                topic = action.get("topic", "")
                words = action.get("words", 500)
                save_path = action.get("save_path", "")
                success, detail = self.write_article(topic, words, save_path)
                return {"action": "write_article", "success": success, "detail": detail}
                
            elif action_type == "web_search":
                query = action.get("query", "")
                success, detail = self.web_search(query)
                return {"action": "web_search", "success": success, "detail": detail}
                
            elif action_type == "navigate":
                url = action.get("url", "")
                success, detail = self.navigate(url)
                return {"action": "navigate", "success": success, "detail": detail}
                
            elif action_type == "browser_click":
                target = action.get("target", "")
                value = action.get("value")
                success, detail = self.browser_click(target, value)
                return {"action": "browser_click", "success": success, "detail": detail}
                
            elif action_type == "file_op":
                return self._execute_file_operation(action)
                
            else:
                return {"action": action_type, "success": False, "detail": f"未知的动作类型: {action_type}"}
                
        except Exception as e:
            log_event("LEGACY_ACTION_ERROR", f"执行传统动作失败: {e}")
            return {"action": action.get("type", "unknown"), "success": False, "detail": f"执行失败: {e}"}

    def _execute_computer_action(self, action: Dict[str, Any]) -> Dict[str, Any]:
        """执行计算机控制动作"""
        try:
            action_type = action.get("type", "")
            
            if action_type == "computer_screenshot":
                # 截图并保存
                region = action.get("region")
                save_path = action.get("save_path", "output/screenshot.png")
                
                screenshot = self.oi_adapter.screenshot(region)
                if screenshot:
                    os.makedirs(os.path.dirname(save_path), exist_ok=True)
                    screenshot.save(save_path)
                    return {"action": "computer_screenshot", "success": True, "detail": f"截图已保存到: {save_path}"}
                else:
                    return {"action": "computer_screenshot", "success": False, "detail": "截图失败"}
            
            elif action_type == "computer_click_text":
                text = action.get("text", "")
                region = action.get("region")
                success = self.oi_adapter.click_text(text, region)
                return {"action": "computer_click_text", "success": success, "detail": f"点击文本 '{text}' {'成功' if success else '失败'}"}
            
            elif action_type == "computer_click_image":
                image_path = action.get("image_path", "")
                confidence = action.get("confidence", 0.8)
                success = self.oi_adapter.click_image(image_path, confidence)
                return {"action": "computer_click_image", "success": success, "detail": f"点击图像 {'成功' if success else '失败'}"}
            
            elif action_type == "computer_type":
                text = action.get("text", "")
                # 在输入前尽量激活最近打开的窗口并聚焦编辑区
                if self.last_opened_app:
                    activated = False
                    # 针对常见应用名与窗口标题做候选匹配（如记事本）
                    candidates = [self.last_opened_app]
                    low = (self.last_opened_app or "").lower()
                    if ("notepad" in low) or ("记事本" in low):
                        candidates += ["记事本", "Notepad", "无标题 - 记事本", "Untitled - Notepad"]
                    for name in candidates:
                        for _ in range(2):
                            if self.oi_adapter.activate_window(name):
                                activated = True
                                break
                            time.sleep(0.3)
                        if activated:
                            break
                    if not activated:
                        for name in candidates:
                            for backend in ("uia", "win32"):
                                if self.computer_controller.focus_window(title_contains=name, backend=backend):
                                    activated = True
                                    break
                                time.sleep(0.2)
                            if activated:
                                break
                    # 再次尝试聚焦输入框
                    if activated:
                        try:
                            self.computer_controller.ensure_message_edit_focus(candidates[0])
                        except Exception:
                            pass
                    time.sleep(0.2)

                # 前台窗口标题校验，提升输入可靠性
                active_title = ""
                activated_title_ok = False
                try:
                    aw = self.oi_adapter.get_active_window()
                    active_title = (aw or {}).get("title", "")
                    # 与候选标题做模糊匹配
                    if self.last_opened_app:
                        low = (self.last_opened_app or "").lower()
                        candidates = [self.last_opened_app]
                        if ("notepad" in low) or ("记事本" in low):
                            candidates += ["记事本", "Notepad", "无标题 - 记事本", "Untitled - Notepad"]
                        for name in candidates:
                            try:
                                if self.computer_controller._fuzzy_match(active_title, name):
                                    activated_title_ok = True
                                    break
                            except Exception:
                                pass
                except Exception:
                    active_title = ""

                # 执行输入（优先 UIA/剪贴板，失败回退 pyautogui）
                success = False
                try:
                    success = self.computer_controller.type_text(text, press_enter=False)
                except Exception:
                    success = False
                if not success:
                    success = self.oi_adapter.type_text(text)

                # 输入后进行视觉验证（限定到目标窗口 ROI，提高准确性）
                verified = False
                target_title = None
                if self.last_opened_app:
                    target_title = self.last_opened_app
                    low = (self.last_opened_app or "").lower()
                    if ("notepad" in low) or ("记事本" in low):
                        # 首选更稳定的候选作为 ROI 标题
                        target_title = "无标题 - 记事本"
                try:
                    roi_title = target_title or (self.last_opened_app or "")
                    # 优先使用 UIA 读取编辑框文本进行确认
                    content = self.computer_controller.read_edit_text(title_contains=roi_title if roi_title else None)
                    verified = bool(content and (text in content))
                    # 若 UIA 读取失败或未包含目标文本，再回退到视觉验证
                    if not verified:
                        if roi_title:
                            verified = self.computer_controller.observe_text(text, title_contains=roi_title)
                        else:
                            verified = self.computer_controller.observe_text(text)
                except Exception:
                    verified = False

                # 如果前台标题匹配且未通过验证，补做一次粘贴重试（优先点击窗口中心再输入）
                if (not verified) and activated_title_ok:
                    try:
                        time.sleep(0.2)
                        typed_ok = False
                        roi_title = target_title or (self.last_opened_app or "")
                        if roi_title:
                            typed_ok = self.computer_controller.type_text_in_window_center_focus(roi_title, text, press_enter=False)
                        else:
                            typed_ok = self.computer_controller.type_text_at_mouse(text, press_enter=False)
                        time.sleep(0.3)
                        # 重试后以 UIA/Win32 文本读取为主进行确认
                        content = self.computer_controller.read_edit_text(title_contains=roi_title if roi_title else None)
                        if content and (text in content):
                            verified = True
                        else:
                            if roi_title:
                                verified = self.computer_controller.observe_text(text, title_contains=roi_title)
                            else:
                                verified = self.computer_controller.observe_text(text)
                    except Exception:
                        pass


                # 统一以验证结果作为成功与否
                final_success = bool(verified)
                try:
                    from .logger import log_event
                    log_event(
                        "TYPE_TEXT_RESULT",
                        f"text_len={len(text)}, success={final_success}, active_title='{active_title}', activated_title_ok={activated_title_ok}"
                    )
                except Exception:
                    pass
                try:
                    from .tts import SpeechFeedback
                    SpeechFeedback().speak("输入文本成功" if final_success else "输入失败，请检查焦点")
                except Exception:
                    pass
                return {"action": "computer_type", "success": final_success, "detail": f"输入文本 '{text}' {'成功' if final_success else '失败'}"}
            
            elif action_type == "computer_key":
                key = action.get("key", "")
                success = self.oi_adapter.press_key(key)
                return {"action": "computer_key", "success": success, "detail": f"按键 '{key}' {'成功' if success else '失败'}"}
            
            elif action_type == "computer_hotkey":
                keys = action.get("keys", [])
                success = self.oi_adapter.hotkey(*keys)
                return {"action": "computer_hotkey", "success": success, "detail": f"组合键 {keys} {'成功' if success else '失败'}"}
            
            elif action_type == "computer_scroll":
                clicks = action.get("clicks", 0)
                x = action.get("x")
                y = action.get("y")
                success = self.oi_adapter.scroll(clicks, x, y)
                return {"action": "computer_scroll", "success": success, "detail": f"滚轮操作 {'成功' if success else '失败'}"}
            
            elif action_type == "computer_window":
                operation = action.get("operation", "")
                title = action.get("title", "")
                
                if operation == "activate":
                    success = self.oi_adapter.activate_window(title)
                    return {"action": "computer_window", "success": success, "detail": f"激活窗口 '{title}' {'成功' if success else '失败'}"}
                elif operation == "find":
                    window_info = self.oi_adapter.find_window(title)
                    success = window_info is not None
                    detail = f"窗口信息: {window_info}" if success else f"未找到窗口 '{title}'"
                    return {"action": "computer_window", "success": success, "detail": detail}
                else:
                    return {"action": "computer_window", "success": False, "detail": f"不支持的窗口操作: {operation}"}
            
            elif action_type == "computer_wait":
                wait_type = action.get("wait_type", "text")
                timeout = action.get("timeout", 10.0)
                
                if wait_type == "text":
                    text = action.get("text", "")
                    region = action.get("region")
                    success = self.oi_adapter.wait_for_text(text, timeout, region)
                    return {"action": "computer_wait", "success": success, "detail": f"等待文本 '{text}' {'成功' if success else '超时'}"}
                
                return {"action": "computer_wait", "success": False, "detail": f"不支持的等待类型: {wait_type}"}
        
        except Exception as e:
            log_event("COMPUTER_ACTION_ERROR", f"执行计算机动作失败: {e}")
            return {"action": action.get("type", "unknown"), "success": False, "detail": f"执行失败: {e}"}

    def _execute_enhanced_app_control(self, action: Dict[str, Any]) -> Dict[str, Any]:
        """执行增强的应用控制"""
        try:
            # 兼容不同来源的字段命名（LLM可能返回 op/app）
            app_name = action.get("app_name") or action.get("app", "")
            operation = action.get("operation") or action.get("op", "")
            params = action.get("params", {})
            app_name = (app_name or "").strip()
            
            # 首先尝试使用原有的计算机控制器
            if hasattr(self, '_execute_app_control_legacy'):
                legacy_result = self._execute_app_control_legacy(action)
                if legacy_result.get("success", False):
                    # 记录最近打开的应用
                    if legacy_result.get("action") == "app_control" and operation == "open":
                        self.last_opened_app = app_name
                    return legacy_result
            
            # 如果原有方法失败，尝试使用 Open Interpreter 适配器
            if operation == "open":
                # 尝试通过点击桌面图标或开始菜单打开应用
                success = self.oi_adapter.click_text(app_name)
                if not success:
                    # 尝试使用快捷键打开（如 Win+R 然后输入应用名）
                    self.oi_adapter.hotkey('win', 'r')
                    time.sleep(0.5)
                    success = self.oi_adapter.type_text(app_name)
                    if success:
                        success = self.oi_adapter.press_key('enter')
                # 记录最近打开的应用
                if success:
                    self.last_opened_app = app_name
                return {"action": "app_control", "success": success, "detail": f"打开应用 '{app_name}' {'成功' if success else '失败'}"}
            
            elif operation == "close":
                # 激活窗口然后关闭（增加重试与UIA聚焦回退）
                activated = False
                for _ in range(2):
                    if self.oi_adapter.activate_window(app_name):
                        activated = True
                        break
                    time.sleep(0.4)
                if not activated:
                    for backend in ("uia", "win32"):
                        if self.computer_controller.focus_window(title_contains=app_name, backend=backend):
                            activated = True
                            break
                        time.sleep(0.3)
                if activated:
                    # 发送 Alt+F4 并验证窗口是否消失
                    self.oi_adapter.hotkey('alt', 'f4')
                    # 验证循环：优先用 pygetwindow，其次用 pywinauto
                    closed = False
                    for i in range(6):
                        time.sleep(0.5)
                        try:
                            if self.oi_adapter.find_window(app_name) is None:
                                closed = True
                                break
                        except Exception:
                            pass
                        # 备用：pywinauto 顶层窗口检查（匹配标题包含 app_name）
                        try:
                            from pywinauto import Desktop as _Desktop
                            remains = False
                            for backend in ("uia", "win32"):
                                try:
                                    wins = _Desktop(backend=backend).windows()
                                    for w in wins:
                                        try:
                                            t = (getattr(w, "window_text", lambda: "")() or "")
                                        except Exception:
                                            t = ""
                                        if app_name.lower() in str(t).lower():
                                            remains = True
                                            break
                                    if remains:
                                        break
                                except Exception:
                                    pass
                            if not remains:
                                closed = True
                                break
                        except Exception:
                            pass
                        # 若仍未关闭，重试一次 Alt+F4
                        if i == 2:
                            try:
                                self.oi_adapter.hotkey('alt', 'f4')
                            except Exception:
                                pass
                    if closed:
                        return {"action": "app_control", "success": True, "detail": f"关闭应用 '{app_name}' 成功"}
                    # 最后回退到旧逻辑（进程级关闭）
                    legacy_close = self._execute_app_control_legacy({"operation": "close", "app_name": app_name})
                    legacy_close["action"] = "app_control"
                    return legacy_close
                # 未能激活：直接回退
                legacy_close = self._execute_app_control_legacy({"operation": "close", "app_name": app_name})
                legacy_close["action"] = "app_control"
                return legacy_close
            
            elif operation == "click":
                target = params.get("target", "")
                # 在指定应用窗口中点击目标
                window_info = self.oi_adapter.find_window(app_name)
                if window_info:
                    region = (window_info['left'], window_info['top'], window_info['width'], window_info['height'])
                    success = self.oi_adapter.click_text(target, region)
                    return {"action": "app_control", "success": success, "detail": f"在 '{app_name}' 中点击 '{target}' {'成功' if success else '失败'}"}
                else:
                    return {"action": "app_control", "success": False, "detail": f"未找到应用窗口 '{app_name}'"}
            
            else:
                return {"action": "app_control", "success": False, "detail": f"未知的应用操作: {operation}"}
                
        except Exception as e:
            log_event("ENHANCED_APP_CONTROL_ERROR", f"执行增强应用控制失败: {e}")
            return {"action": "app_control", "success": False, "detail": f"执行失败: {e}"}

    # 新增：旧逻辑包装，直接调用基础执行器的应用控制
    def _execute_app_control_legacy(self, action: Dict[str, Any]) -> Dict[str, Any]:
        try:
            op = action.get("operation") or action.get("op", "")
            app = action.get("app_name") or action.get("app", "")
            ok, detail = super()._execute_app_control(op, app)
            return {"action": "app_control", "success": ok, "detail": detail}
        except Exception as e:
            log_event("LEGACY_APP_WRAPPER_ERROR", f"{e}")
            return {"action": "app_control", "success": False, "detail": f"旧逻辑执行失败: {e}"}
    def _execute_with_oi_adapter(self, action: Dict[str, Any]) -> Dict[str, Any]:
        """使用 Open Interpreter 适配器执行未知动作"""
        try:
            # 轻量级字段归一化，兼容 LLM 返回的不同键名
            at = action.get("type", "")
            if at == "type_text":
                # 统一到 OI 适配器期望的键名
                if "text" not in action and "content" in action:
                    action = {**action, "text": action.get("content", "")}
            elif at == "click_text":
                if "text" not in action and "value" in action:
                    action = {**action, "text": action.get("value", "")}
            
            success, detail = self.oi_adapter.execute_computer_action(action)
            return {"action": action.get("type", "unknown"), "success": success, "detail": detail}
        except Exception as e:
            log_event("OI_ADAPTER_ERROR", f"Open Interpreter 适配器执行失败: {e}")
            return {"action": action.get("type", "unknown"), "success": False, "detail": f"执行失败: {e}"}
    
    def _execute_system_control(self, action: Dict[str, Any]) -> Dict[str, Any]:
        """执行系统控制操作"""
        try:
            operation = action.get("operation", "")
            
            if operation == "volume":
                level = action.get("level", 50)
                # 使用快捷键调节音量
                current_volume = 0  # 假设当前音量为0，实际应该获取系统音量
                if level > current_volume:
                    # 增加音量
                    for _ in range((level - current_volume) // 2):
                        self.oi_adapter.press_key('volumeup')
                        time.sleep(0.1)
                else:
                    # 减少音量
                    for _ in range((current_volume - level) // 2):
                        self.oi_adapter.press_key('volumedown')
                        time.sleep(0.1)
                
                return {"action": "system_control", "success": True, "detail": f"音量已调节到 {level}%"}
            
            elif operation == "brightness":
                level = action.get("level", 50)
                # 打开设置调节亮度
                self.oi_adapter.hotkey('win', 'i')
                time.sleep(1)
                if self.oi_adapter.click_text("系统"):
                    time.sleep(0.5)
                    if self.oi_adapter.click_text("显示"):
                        time.sleep(0.5)
                        # 这里可以进一步实现亮度调节逻辑
                        return {"action": "system_control", "success": True, "detail": f"已打开显示设置"}
                
                return {"action": "system_control", "success": False, "detail": "调节亮度失败"}
            
            else:
                return {"action": "system_control", "success": False, "detail": f"不支持的系统操作: {operation}"}
                
        except Exception as e:
            log_event("SYSTEM_CONTROL_ERROR", f"执行系统控制失败: {e}")
            return {"action": "system_control", "success": False, "detail": f"执行失败: {e}"}
    
    # ==================== 新增的便捷方法 ====================
    
    def take_screenshot(self, save_path: str = "output/screenshot.png", region: Optional[Tuple[int, int, int, int]] = None) -> Tuple[bool, str]:
        """截图便捷方法"""
        try:
            screenshot = self.oi_adapter.screenshot(region)
            if screenshot:
                os.makedirs(os.path.dirname(save_path), exist_ok=True)
                screenshot.save(save_path)
                return True, f"截图已保存到: {save_path}"
            else:
                return False, "截图失败"
        except Exception as e:
            return False, f"截图失败: {e}"
    
    def smart_click(self, target: str, app_name: Optional[str] = None) -> Tuple[bool, str]:
        """智能点击：自动判断是文本还是图像"""
        try:
            region = None
            if app_name:
                window_info = self.oi_adapter.find_window(app_name)
                if window_info:
                    region = (window_info['left'], window_info['top'], window_info['width'], window_info['height'])
            
            # 首先尝试作为文本点击
            if self.oi_adapter.click_text(target, region):
                return True, f"成功点击文本: {target}"
            
            # 如果文本点击失败，尝试作为图像点击
            if os.path.exists(target):
                if self.oi_adapter.click_image(target):
                    return True, f"成功点击图像: {target}"
            
            return False, f"无法点击目标: {target}"
            
        except Exception as e:
            return False, f"智能点击失败: {e}"
    
    def execute_sequence(self, actions: List[Dict[str, Any]], delay: float = 0.5) -> List[Dict[str, Any]]:
        """执行动作序列，每个动作之间有延迟"""
        results = []
        for i, action in enumerate(actions):
            if i > 0:
                time.sleep(delay)
            result = self.execute_actions([action])[0]
            results.append(result)
            # 如果某个动作失败，可以选择继续或停止
            if not result.get("success", False):
                log_event("SEQUENCE_WARNING", f"序列中的动作 {i+1} 失败: {result.get('detail', '')}")
        return results